package com.nuanshui.heatedloan.userinfo.service.wechat;

import com.alibaba.fastjson.JSON;
import com.nuanshui.framework.res.UploadRequest;
import com.nuanshui.heatedloan.baseservice.service.CommonServiceImpl;
import com.nuanshui.framework.consts.TransactionManagerType;
import com.nuanshui.framework.lang.MapUtil;
import com.nuanshui.framework.lang.SysStringUtils;
import com.nuanshui.framework.res.ResourceFacade;
import com.nuanshui.framework.res.qiniu.UpLoadFileVO;
import com.nuanshui.framework.security.SHA1;
import com.nuanshui.framework.utils.LogUtil;
import com.nuanshui.framework.utils.model.StringObjPair;
import com.nuanshui.framework.utils.redis.JedisUtil;
import com.nuanshui.framework.utils.wechat.PushMsgCallBack;
import com.nuanshui.heatedloan.constant.ServiceConstant;
import com.nuanshui.heatedloan.middleware.whatchat.util.WechatPPUtil;
import com.nuanshui.heatedloan.baseservice.facade.AdvertisementService;
import com.nuanshui.heatedloan.userinfo.dal.mapper.UsersMapper;
import com.nuanshui.heatedloan.userinfo.dal.mapper.WeixinUserMapper;
import com.nuanshui.heatedloan.userinfo.facade.UserService;
import com.nuanshui.heatedloan.userinfo.facade.UserWeixinService;
import com.nuanshui.heatedloan.userinfo.facade.thirdlogin.ThirdUserService;
import com.nuanshui.heatedloan.userinfo.facade.thirdlogin.ThirdUserServiceConstant;
import com.nuanshui.heatedloan.userinfo.facade.thirdlogin.ThirdUserServiceFactory;
import com.nuanshui.heatedloan.userinfo.facade.wechat.WeChatService;
import com.nuanshui.heatedloan.userinfo.form.BoundUserForm;
import com.nuanshui.heatedloan.userinfo.model.User;
import com.nuanshui.heatedloan.userinfo.model.UserWeixinMsg;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.sword.lang.JaxbParser;
import org.sword.wechat4j.util.RandomStringGenerator;
import weixin.popular.bean.ticket.Ticket;
import weixin.popular.bean.sns.SnsToken;
import weixin.popular.api.TicketAPI;
import com.alibaba.dubbo.config.annotation.Reference;
import com.nuanshui.heatedloan.constant.GlobalParam;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service(ServiceConstant.WeChatService)
@Transactional(readOnly=true,value=TransactionManagerType.USER_INFO_TRANSACTION_MANAGER)
public class WeChatServiceImpl extends CommonServiceImpl implements WeChatService {

	private static final String JSAPI_TICKET_KEY = "jsapi_ticket_wechat";
	
	private static final String TRADE_TYPE = "JSAPI";
	
	private static final String HTTPS_API_MCH_WEIXIN_QQ_COM_PAY_UNIFIEDORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";
	
	private static final Logger logger = LoggerFactory.getLogger(WeChatServiceImpl.class);
	
	@Autowired
	private JedisUtil jedis;
	

	
	@Autowired
	private WeixinUserMapper weixinUserMapper;
	
	@Autowired
	private UserService userService;
	@Autowired
	private UserWeixinService userWeixinService;
	
	@Autowired
	private UsersMapper usersMapper;

	@Autowired
	@Qualifier("ThirdUserServiceFactory")
	private ThirdUserServiceFactory thirdUserServiceFactory;

	@Reference(url = GlobalParam.BASESERVICE_DUBBO_SERVER, timeout = GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private AdvertisementService advertisementService;

	@Autowired
	ResourceFacade resourceFacade;

	@Autowired
	JedisUtil jedisUtil;

	public WeChatServiceImpl() {
	}

	/**
	 * 通过微信第三方jar包来获取ticket
	 * @author zhousishang
	 * @return
	 */
	private String getApiTicketByThird(){
		String jsapi_ticket =jedis.get(JSAPI_TICKET_KEY);
		if (SysStringUtils.isEmpty(jsapi_ticket)) {
			    String access_token=WechatPPUtil.getAccessToken();
				Ticket ticket= TicketAPI.ticketGetticket(access_token);
				if (ticket != null){
					jsapi_ticket =ticket.getTicket();
				}
				LogUtil.info(logger, "The updated jsApiTicket=" + jsapi_ticket);
			    jedis.set(JSAPI_TICKET_KEY, jsapi_ticket);
			    jedis.expire(JSAPI_TICKET_KEY, 1800);
		}
		return jsapi_ticket;
	}



	@Override
	public Map<String, Object> getSignatureInfo(String signUrl) {
		/**
		 * @modifyBy: zhousishang  2017/06/9
		 * @description 摒弃公司自己封装微信工具api，使用第三方工具包
		 */
		String  apiTicket = getApiTicketByThird();

		String timestamp = System.currentTimeMillis() / 1000 + ""; // 时间戳
		String nonceStr = RandomStringGenerator.generate(12); // 长度12的字符随机字符串
		
		LogUtil.info(logger, "--------------开始获取校验url信息---------------------------");
		
		LogUtil.info(logger, "signUrl =" + signUrl);
		LogUtil.info(logger, "apiTicket =" + apiTicket);
		LogUtil.info(logger, "timestamp =" + timestamp);
		LogUtil.info(logger, "nonceStr =" + nonceStr);
		
		ArrayList<StringObjPair> paramList=new ArrayList<StringObjPair>();
		
		paramList.add(new StringObjPair("jsapi_ticket", apiTicket));
		paramList.add(new StringObjPair("noncestr", nonceStr));
		paramList.add(new StringObjPair("timestamp", timestamp));
		paramList.add(new StringObjPair("url", signUrl));

		LogUtil.info(logger, "jsapi_ticket = " + apiTicket);
		
		String paramsStr =MapUtil.params(paramList);
		LogUtil.info(logger, "paramsStr =" + paramsStr);

		String signature = new SHA1().getDigestOfString(paramsStr.getBytes()); // SHA1算法生成数字签名
		
		LogUtil.info(logger, "signature =" + signature);
		
		int code = 0;
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("timestamp", timestamp);
		map.put("nonceStr", nonceStr);
		map.put("signature", signature);
		map.put("code", code);
		
		return map;
	}
	
	/**
	 * 构建XML解析器JAXBPaser
	 *
	 * @param clazz
	 * @return
	 */
	private static JaxbParser buildJAXBParser(
			@SuppressWarnings("rawtypes") Class clazz) {
		JaxbParser parser = new JaxbParser(clazz);
		Field[] fields = clazz.getDeclaredFields();
		String[] fieldNames = new String[fields.length];
		for (int i = 0; i < fields.length; i++) {
			fieldNames[i] = fields[i].getName();
		}
		parser.setCdataNode(fieldNames);
		return parser;
	}
	

	
	@Override
	@Transactional(value=TransactionManagerType.USER_INFO_TRANSACTION_MANAGER)
	public User syncUserInfo() {
		/**
		 * @modifyBy: zhousishang  2017/06/9
		 * @description 摒弃公司自己封装微信工具api，使用第三方工具包
		 */
		String openid= getCurrentOpenId();
		String res =WechatPPUtil.getStrByOpenId(openid);

		ThirdUserService thirdUserService=thirdUserServiceFactory.GetThirdUserService(ThirdUserServiceConstant.WeiboUserService);

		User user = thirdUserService.loadUser(openid);
		BoundUserForm boundUserForm = JSON.parseObject(res, BoundUserForm.class);
		user.setNick(boundUserForm.getNickname());
		uploadThirdUserHeadImg(boundUserForm);
		user.setAvatar(boundUserForm.getImage());
		if(SysStringUtils.isNotEmpty(boundUserForm.getSex())){//防止出现异常
			user.setSex(Integer.parseInt(boundUserForm.getSex()));
		}
		user.setLocation(boundUserForm.getCountry() + "-"
				+ boundUserForm.getProvince() + "-" + boundUserForm.getCity());
		userService.updateUserInfo(user, false);
		return user;
	}
	
	/**
	 * 获取微信头像的七牛key
	 * 
	 * @author Junyan2015
	 * @date 2016年4月18日 上午11:04:45
	 * @since
	 */
	@Override
	public BoundUserForm uploadThirdUserHeadImg(BoundUserForm boundUserForm) {
		if (StringUtils.isNotEmpty(boundUserForm.getHeadimgurl())) {

			UploadRequest request=new UploadRequest();
			request.setFetchUrl(boundUserForm.getHeadimgurl());

			UpLoadFileVO item=resourceFacade.uploadFile(request).getFile();
			if(item!=null)
			{
				boundUserForm.setImage(item.getKey());
			}
		}
		
		return boundUserForm;
	}
	
	@Override
	@Transactional(value=TransactionManagerType.USER_INFO_TRANSACTION_MANAGER)
	public User login(String code, String redirectUrl) {
		/**
		 * @modifyBy: zhousishang  2017/06/9
		 * @description 摒弃公司自己封装微信工具api，使用第三方工具包
		 */
		SnsToken snsToken=WechatPPUtil.getSnsToken(code);
		String openId = snsToken.getOpenid();

		ThirdUserService thirdUserService=thirdUserServiceFactory.GetThirdUserService(ThirdUserServiceConstant.WeiboUserService);
		User user = thirdUserService.loadUser(openId);
		if (user == null) {// 账号不存在，创建新的账号
			//String string = WechatUtil.getWechatUserByWechatOpenId(wechat);
			String string =WechatPPUtil.getStrByOpenId(openId);

			BoundUserForm boundUserForm = JSON.parseObject(string,
					BoundUserForm.class);
			uploadThirdUserHeadImg(boundUserForm);

			user = thirdUserService.insertUser(boundUserForm);
		}
		
		return user;
		
	}
	
	@Override
	public int payAddress(String code, String url,Map<String, Object> map) {
		int result=0;
		if (code == null || url == null)
			result=1;
			error("code，url不能为空！");

		/**
		 * @modifyBy: zhousishang  2017/06/9
		 * @description 摒弃公司自己封装微信工具api，使用第三方工具包
		 */
		String appId =WechatPPUtil.getAppid();
		String accessToken = null;
		SnsToken snsToken=WechatPPUtil.getSnsToken(code);
		if (snsToken ==null)
			result=2;
		error("openid未获取！请检查code值或appid");
		accessToken = snsToken.getAccess_token();

		String nonceStr = RandomStringGenerator.generate(12);
		String timeStamp = System.currentTimeMillis() / 1000 + "";

		ArrayList<StringObjPair> list=new ArrayList<StringObjPair>();
		list.add(new StringObjPair("accesstoken",accessToken));
		list.add(new StringObjPair("appid",appId));
		list.add(new StringObjPair("noncestr",nonceStr));
		list.add(new StringObjPair("timestamp",timeStamp));
		list.add(new StringObjPair("url",url));
		String string1 = MapUtil.params(list);
		
		
		String addrSign = (new SHA1()).getDigestOfString(string1.getBytes());
		
		map.put("timeStamp", timeStamp);
		map.put("nonceStr", nonceStr);
		map.put("addrSign", addrSign);
		map.put("scope", "jsapi_address");
		map.put("signType", "sha1");
		map.put("appId", appId);
		
		logger.info("地址共享签名--------" + addrSign);
		
		
		return result;
	}
	
	@Override
	public void pushMsg() {
		
		String result = null;
		try {
			int len;
			byte[] b = new byte[1024];
			ByteArrayOutputStream stream = new ByteArrayOutputStream();
			//InputStream servletInputStream = this.getRequest().getInputStream();
			InputStream servletInputStream=getRequest().getInputStream();
			while ((len = servletInputStream.read(b)) != -1) {
				stream.write(b, 0, len);
			}
			result = stream.toString(Consts.UTF_8.name());
		} catch (IOException e) {
			logger.error("消息回调接受数据失败", e);
		}

		logger.info("消息回调的内容为" + result);
		JaxbParser parser = buildJAXBParser(PushMsgCallBack.class);
		PushMsgCallBack info = (PushMsgCallBack) parser.toObj(result);
		logger.info(info.toString());
		UserWeixinMsg msg = new UserWeixinMsg();
		msg.setCreateTime(new Date(info.getCreateTime() * 1000));
		msg.setEvent(info.getEvent());
		msg.setFromUserName(info.getFromUserName());
		msg.setMsgId(info.getMsgID() + "");
		msg.setMsgType(info.getMsgType());
		msg.setStatus(info.getStatus());
		msg.setToUserName(info.getToUserName());
		userWeixinService.pushMsgSave(msg);
	}


	@Override
	public void bindWechatAccount(BoundUserForm boundUserForm) {
		weixinUserMapper.insertUserWeixin(boundUserForm);
	}
}
